#include "Ctrl.h"

#if InterpreterPattern_ 

// 演奏内容类
class PlayContext
{

private:
	// 演奏文本
	string m_text;
public :
	string GetPlayText()const {
		return m_text;
	}
	void SetPlayText(const string _str) {
		m_text = _str;
	}
};

// 表达式类
class Expression
{
public:
	void Interpret(PlayContext* pContext){
		if (pContext->GetPlayText().length() == 0) {
			return;
		}
		else {
			string playKey = pContext->GetPlayText().substr(0, 1);
			pContext->SetPlayText(pContext->GetPlayText().substr(2));
			double playValue = std::stod(pContext->GetPlayText().substr(0, pContext->GetPlayText().find(" ")));
			pContext->SetPlayText(pContext->GetPlayText().substr(pContext->GetPlayText().find(" ") + 1));
			Excute(playKey, playValue);
		}
	}
	virtual void Excute(string key, double value) = 0;
};

// 音符类
class Note : public Expression 
{
public:
	void Excute(string key, double value)override {
		string note = "";
		if (key == "C") {
			note = "1";
		}
		else if (key == "D") {
			note = "2";
		}
		else if (key == "E") {
			note = "3";
		}
		else if (key == "F") {
			note = "4";
		}
		else if (key == "G") {
			note = "5";
		}
		else if (key == "A") {
			note = "6";
		}
		else if (key == "B") {
			note = "7";
		}
		cout << note << " ";
	}
	
};

// 音阶类
class Scale : public Expression
{
public :
	void Excute(string key, double value) override {
		string scale = "";
		switch (int(value))
		{
		case 1 :
			scale = "低音";
			break;
		case 2 :
			scale = "中音";
			break;
		case 3 :
			scale = "高音";
			break;
		}
		cout << scale << " ";
	}
};



int main() {
	
	PlayContext* pContext = new PlayContext();
	cout << "上海滩：" << endl;
	pContext->SetPlayText("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ");
	Expression* pExpression = nullptr;

	try {
		while (pContext->GetPlayText().length() > 0) {
			string str = pContext->GetPlayText().substr(0, 1);
			if (str == "O") {
				pExpression = new Scale();
			}
			else if (str >= "A" && str <= "G" || str == "P") {
				pExpression = new Note();
			}
			pExpression->Interpret(pContext);
		}
	}
	catch (exception ex) {
		cout << ex.what() << endl;
	}
}



#endif